home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 2007 December
/
PCWKCD1207B.iso
/
Blogowanie poza sfera
/
Flock 1.0 beta
/
flock-1.0RC3.en-US.win32.exe
/
flock
/
components
/
flockXmlRpc.js
< prev
next >
Wrap
Text File
|
2007-10-18
|
13KB
|
384 lines
// BEGIN FLOCK GPL
//
// Copyright Flock Inc. 2005-2007
// http://flock.com
//
// This file may be used under the terms of of the
// GNU General Public License Version 2 or later (the "GPL"),
// http://www.gnu.org/licenses/gpl.html
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
// for the specific language governing rights and limitations under the
// License.
//
// END FLOCK GPL
//
const CC = Components.classes;
const CI = Components.interfaces;
const CR = Components.results;
const CU = Components.utils;
function DEBUG(X) { }
//function DEBUG(X) { debug ('flockXmlRpc.js: '+X+'\n'); }
CU.import("resource:///modules/FlockXPCOMUtils.jsm");
CU.import("resource:///modules/ISO8601DateUtils.jsm");
const FLOCK_XMLRPC_CLASS_NAME = "Flock XML-RPC";
const FLOCK_XMLRPC_CLASS_ID =
Components.ID("{709f57f4-a4e4-41bb-a38d-86309fbc4858}");
const FLOCK_XMLRPC_CONTRACT_ID = "@flock.com/xmlrpc/server;1";
const Base64 = {
chars: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',
encode: function (aInput) {
var output = '';
while (aInput.length > 0) {
output += Base64.chars[aInput.charCodeAt(0) >> 2];
output += Base64.chars[((aInput.charCodeAt(0)&0x03) << 4) |
(aInput.length>1?((aInput.charCodeAt(1)&0xF0) >> 4):0)];
output += Base64.chars[aInput.length>1?
((aInput.charCodeAt(1)&0x0F)<<2) |
(aInput.length>2?((aInput.charCodeAt(2)&0xC0) >> 6):0):64];
output += Base64.chars[aInput.length>2?
(aInput.charCodeAt(2)&0x3F):64];
if (aInput.length > 3) {
aInput = aInput.substr (3);
} else {
break;
}
}
return output;
},
decode: function (aInput) {
const regexp = new RegExp ('[^'+Base64.chars+']', 'g');
var output = '';
aInput = aInput.replace (regexp, '');
// FIXME: aInput MUST now be a multiple of four characters long
function sixbits (i) {
if (i == '=') return 0;
return Base64.chars.indexOf (i);
}
while (aInput.length >= 4) {
output += String.fromCharCode ((sixbits (aInput[0]) << 2) |
(sixbits (aInput[1]) >> 4));
if (aInput[2] == '=') {
break;
}
output += String.fromCharCode ((sixbits (aInput[1]) << 4) |
(sixbits (aInput[2]) >>2));
if (aInput[3] == '=') {
break;
}
output += String.fromCharCode (((sixbits (aInput[2]) << 6) & 0xC0) |
sixbits (aInput[3]));
aInput = aInput.substr (4);
}
return output;
}
}
var XmlRpcXml = {
build: function XRX_build(value) {
if (value == undefined) {
return null;
}
// FIXME: do the next two blocks have the desired effect?
if (value.QueryInterface) {
value = value.QueryInterface(flockIXmlRpcValue);
if (value == null) {
return null;
}
} else {
return null;
}
try {
value = value.QueryInterface(flockIXmlRpcValue);
} catch (e) {
return value.toString();
}
switch (value.XmlRpcType) {
case flockIXmlRpcValue.TYPE_INT:
return <int>{ String(value.IntValue) }</int>;
case flockIXmlRpcValue.TYPE_BOOLEAN:
return <boolean>{ value.BooleanValue ? 1 : 0 }</boolean>;
case flockIXmlRpcValue.TYPE_STRING:
return <string>{ value.StringValue }</string>;
case flockIXmlRpcValue.TYPE_DOUBLE:
return <double>{ String(value.DoubleValue) }</double>;
case flockIXmlRpcValue.TYPE_DATETIME:
var date = new Date();
date.setTime(value.DateTimeValue * 1000);
var datetime = ISO8601DateUtils.create(date);
return <dateTime.iso8601>{datetime}</dateTime.iso8601>;
case flockIXmlRpcValue.TYPE_ARRAY:
var elements = value.ArrayElements({});
var array = <array><data/></array>;
for (var i = 0; i < elements.length; i++) {
var q = XmlRpcXml.build(elements[i]);
if (q == null) {
continue;
}
array.data.foo = <value>{q}</value>;
}
return array;
case flockIXmlRpcValue.TYPE_STRUCT:
var keys = value.StructKeys({});
var struct = <struct/>;
for (var i in keys) {
var q = XmlRpcXml.build(value.StructItem(keys[i]));
if (q == null) {
continue;
}
struct.foo = <member>
<name>{keys[i]}</name>
<value>{q}</value>
</member>;
}
return struct;
case flockIXmlRpcValue.TYPE_BASE64:
return <base64>{ Base64.encode(value.Base64Value) }</base64>;
default:
throw "error building XML";
return null;
}
},
parse: function XRX_parse(xml) {
DEBUG("XmlRpcXml.parse:" + xml);
if (xml == undefined) {
// this is the empty string
return "";
}
if (xml.nodeKind() == "text") {
// the default type in string
return XmlRpcValue.String(xml.toString());
}
switch (xml.name().toString()) {
case "int":
case "i4":
return XmlRpcValue.Int(parseInt(xml.text()));
case "boolean":
return XmlRpcValue.Boolean(parseInt(xml.text()) == 1);
case "string":
return XmlRpcValue.String (xml.text().toString());
case "double":
return XmlRpcValue.Double(parseFloat (xml.text()));
case "dateTime.iso8601":
var val = xml.text().toString();
var myDate = ISO8601DateUtils.parse(val);
return XmlRpcValue.DateTime(myDate);
case "array":
var arr = [];
for (var i = 0; i < xml.data.value.length(); i++) {
arr.push(XmlRpcXml.parse(xml.data.value[i].children()[0]));
}
return XmlRpcValue.Array(arr);
case "struct":
var struct = {};
for (var i = 0; i < xml.member.length(); i++) {
struct[xml.member[i].name.text()] =
XmlRpcXml.parse(xml.member[i].value.children()[0]);
}
return XmlRpcValue.Struct(struct);
case "base64":
return XmlRpcValue.Base64(Base64.decode(xml.text().toString()));
default:
throw "error parsing XML";
}
}
}
// flockXmlRpcServer object
function flockXmlRpcServerComponent() {
this.mURL = null;
this.mTimeout = null;
}
flockXmlRpcServerComponent.prototype = new FlockXPCOMUtils.genericComponent(
FLOCK_XMLRPC_CLASS_NAME,
FLOCK_XMLRPC_CLASS_ID,
FLOCK_XMLRPC_CONTRACT_ID,
flockXmlRpcServerComponent,
0, // nsIClassInfo flags
[CI.flockIXmlRpcServer]
);
flockXmlRpcServerComponent.prototype.init =
function XRSC_init(aURL) {
DEBUG('flockXmlRpcServer.init("' + aURL + '")');
this.mURL = aURL;
this.mTimeout = 120 * 1000;
}
flockXmlRpcServerComponent.prototype.call =
function XRSC_call(aMethod, aArguments, aListener) {
// var aOptionalTimeoutInSeconds = 10;
DEBUG("flockXmlRpcServer.call("
+ aMethod + ", "
+ aArguments + ", "
+ aListener + ")\n");
if (aArguments.XmlRpcType != flockIXmlRpcValue.TYPE_ARRAY) {
aListener.onError("the arguments must be in an xmrpc array");
return;
}
var methodCall = <methodCall/>;
methodCall.methodName = aMethod;
var arguments = aArguments.ArrayElements({});
DEBUG("XMLRPC: got " + arguments.length + " arguments");
for (var i in arguments) {
DEBUG("XMLRPC: adding arg " + XmlRpcXml.build(arguments[i]));
methodCall.params.param +=
<param>
<value>{ XmlRpcXml.build(arguments[i]) }</value>
</param>;
}
var url = this.mURL;
var timeout = this.mTimeout;
var callback = {};
callback.notify = function XRSC_call_callback_notify(timer) {
var xhr = CC["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(CI.nsIXMLHttpRequest);
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "text/xml");
// FIXME: what about charsets?
// FIXME: should we make this configurable?
xhr.overrideMimeType("text/xml");
xhr.onreadystatechange = function XRSC_call_xhr(aEvent) {
if (xhr.readyState == 4) {
if (!xhr.responseXML) {
aListener.onError (xhr.responseText);
return;
}
if (xhr.status != 200) {
aListener.onError (xhr.statusText);
return;
}
//save the state of the XML object directives
Orig_XML_ignoreComments = XML.ignoreComments;
Orig_XML_ignoreProcessingInstructions = XML.ignoreProcessingInstructions;
Orig_XML_ignoreWhitespace = XML.ignoreWhitespace;
Orig_XML_prettyPrinting = XML.prettyPrinting;
Orig_XML_prettyIndent = XML.prettyIndent;
//set them to what we need for the parser to behave
XML.ignoreComments = true;
XML.ignoreProcessingInstructions = true;
XML.ignoreWhitespace = true;
XML.prettyPrinting = false;
XML.prettyIndent = false;
//var response = new XML(xhr.responseXML);
var serializer = CC["@mozilla.org/xmlextras/xmlserializer;1"]
.createInstance(CI.nsIDOMSerializer);
var xmlStr =
serializer.serializeToString(xhr.responseXML.documentElement);
var response = new XML(xmlStr);
if (response.name() != "methodResponse" ||
!(response.params.param.value.length() == 1 ||
response.fault.value.struct.length() == 1))
{
aListener.onError("invalid response XML: " + xhr.responseText);
return;
}
if (response.params.param.value.length() == 1) {
var resp = XmlRpcXml.parse(response.params.param.value.children()[0]);
aListener.onResult(resp);
//put them back like we found them before we return
XML.ignoreComments = Orig_XML_ignoreComments;
XML.ignoreProcessingInstructions = Orig_XML_ignoreProcessingInstructions;
XML.ignoreWhitespace = Orig_XML_ignoreWhitespace;
XML.prettyPrinting = Orig_XML_prettyPrinting;
XML.prettyIndent = Orig_XML_prettyIndent;
return;
}
var fault =
XmlRpcValue.ToJavaScript(XmlRpcXml.parse(response.fault.value.struct));
if (fault["faultCode"] == undefined ||
fault["faultString"] == undefined)
{
aListener.onError("invalid response XML: " + xhr.responseText);
//put them back like we found them before we return
XML.ignoreComments = Orig_XML_ignoreComments;
XML.ignoreProcessingInstructions = Orig_XML_ignoreProcessingInstructions;
XML.ignoreWhitespace = Orig_XML_ignoreWhitespace;
XML.prettyPrinting = Orig_XML_prettyPrinting;
XML.prettyIndent = Orig_XML_prettyIndent;
return;
}
aListener.onFault(fault["faultCode"], fault["faultString"]);
//put them back like we found them before we return
XML.ignoreComments = Orig_XML_ignoreComments;
XML.ignoreProcessingInstructions = Orig_XML_ignoreProcessingInstructions;
XML.ignoreWhitespace = Orig_XML_ignoreWhitespace;
XML.prettyPrinting = Orig_XML_prettyPrinting;
XML.prettyIndent = Orig_XML_prettyIndent;
return;
}
}
DEBUG('XMLRPC: sending: '
+ '<?xml version="1.0"?>\n'
+ methodCall.toXMLString());
DEBUG('XMLRPC timeout is "' + timeout + '"');
var timeoutCallback= {};
timeoutCallback.notify = function XRSC_call_timeout_notify(timer) {
DEBUG("timeoutCallback.notify called");
if (xhr == null) {
DEBUG("flockXmlRpcServerComponent.prototype.call.timeoutCallback "
+ "called with null request!!");
} else if ((xhr != null) && (xhr.readyState != 4)) {
DEBUG("XMLRPC timed out");
//the request still exists and hasn't completed
delete xhr["onreadystatechange"]; //Kill the callback function
xhr.abort(); //abort the request
aListener.onError("timeout"); //return an error to the caller
}
}
var timeOutTimer = CC["@mozilla.org/timer;1"]
.createInstance(CI.nsITimer);
timeOutTimer.initWithCallback(timeoutCallback, timeout,
CI.nsITimer.TYPE_ONE_SHOT);
xhr.send('<?xml version="1.0"?>\n' + methodCall.toXMLString());
}
var timer = CC["@mozilla.org/timer;1"].createInstance(CI.nsITimer);
timer.initWithCallback(callback, 1, CI.nsITimer.TYPE_ONE_SHOT);
}
// load the XMLRPC helper
var loader = CC['@mozilla.org/moz/jssubscript-loader;1']
.getService(CI.mozIJSSubScriptLoader);
loader.loadSubScript("chrome://flock/content/xmlrpc/xmlrpchelper.js");
var NSGetModule =
FlockXPCOMUtils.generateNSGetModule(FLOCK_XMLRPC_CLASS_NAME,
[flockXmlRpcServerComponent]);